package sudoku.support

import sudoku.draft.Pos

/**
 * @author flutterdash@qq.com
 * @since 2021/9/30 19:03
 */

typealias Board = Array<IntArray>

const val side = 9

fun defaultTestBoard(): Board {
    return arrayOf(
        intArrayOf(5, 3, 0, 0, 7, 0, 0, 0, 0),
        intArrayOf(6, 0, 0, 1, 9, 5, 0, 0, 0),
        intArrayOf(0, 9, 8, 0, 0, 0, 0, 6, 0),
        intArrayOf(8, 0, 0, 0, 6, 0, 0, 0, 3),
        intArrayOf(4, 0, 0, 8, 0, 3, 0, 0, 1),
        intArrayOf(7, 0, 0, 0, 2, 0, 0, 0, 6),
        intArrayOf(0, 6, 0, 0, 0, 0, 2, 8, 0),
        intArrayOf(0, 0, 0, 4, 1, 9, 0, 0, 5),
        intArrayOf(0, 0, 0, 0, 8, 0, 0, 7, 9)
    )
}

fun getBoxOf(pos: Pos): List<Pos> {
    val start = Pos(pos.row / 3, pos.col / 3)
    val box = ArrayList<Pos>()
    for (r in 0 until 3) {
        for (c in 0 until 3) {
            box.add(Pos(start.row + r, start.col + c))
        }
    }
    return box
}

fun emptyBoard(): Board = Array(side) { IntArray(side) { 0 } }

fun Board.print(): Board {
    printBoard(this)
    return this
}

fun Board.copy(): Board {
    val replicated = emptyBoard()
    for (r in 0 until side) {
        for (c in 0 until side) {
            replicated[r][c] = this[r][c]
        }
    }
    return replicated
}

/**
 * 局部
 *
 *   1 2 3 | 4 5 6 | 7 8 9
 *   4 5 6 | 7 8 9 | 1 2 3
 *   7 8 9 | 1 2 3 | 4 5 6
 *   - - - + - - - + - - -
 *   1 2 3 | 4 5 6 + 7 8 9
 *   . . .   . . .
 */
fun printBoard(board: Board) {
    println(buildTextBoard(board))
}

fun buildTextBoard(board: Board): String {
    val buff = StringBuilder()
    val consoleBoard = buildPlaceholderBoard(board)
    for (r in consoleBoard.indices) {
        for (c in consoleBoard[r].indices) {
            buff.append(' ')
            buff.append(switchPlaceholder(consoleBoard[r][c]))
        }
        buff.append('\n')
    }
    return buff.toString()
}

fun buildPlaceholderBoard(board: Board): List<List<Int>> {
    val consoleBoard = ArrayList<List<Int>>()
    val splitLine = intArrayOf(-2, -2, -2, -3, -2, -2, -2, -3, -2, -2, -2)
    for (r in board.indices) {
        val newLine = board[r].toMutableList()
        newLine.add(3, -1)
        newLine.add(7, -1)
        consoleBoard.add(newLine)
        if (r == 2 || r == 5)
            consoleBoard.add(splitLine.asList())
    }
    return consoleBoard
}

fun switchPlaceholder(placeholder: Int): String {
    return when (placeholder) {
        0 -> "."
        -1 -> "|"
        -2 -> "-"
        -3 -> "+"
        else -> placeholder.toString()
    }
}
